package simtester.test;

import static org.junit.Assert.*;

import com.gmongo.GMongo
import com.mongodb.DBRef
import geb.junit4.GebReportingTest
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test
import simtester.test.pages.*
import simtester.test.Utils

class RunScriptRepeatTests extends GebReportingTest {
    static def testConfig
    static def db
    def testusername = 'Linh'
    def testpw = 'pass'
    def testrunName = 'DefaultTest'

    @BeforeClass
    static void setUpAll() {
        testConfig = new ConfigSlurper().parse(new File('grails-app/conf/SimTesterConfig.groovy').toURI().toURL())
        db = new GMongo().getDB(testConfig.test.dbname)
    }
    
    @AfterClass
    static void tearDownAll() {
        Utils.dropCollections(db)
    }
    
    @Before
    public void setUp() throws Exception {
        db.user << [_id: 12L, team: new DBRef(null, 'team', 10L), username: testusername, password: testpw.encodeAsMD5(), dateCreated: new Date(), lastUpdated: new Date()]
        def user = db.user.findOne(username: testusername)
        def testScript = '''\
package simtester.agent
import geb.*
import groovyx.net.http.ContentType
class AgentScript {
  static runtest(args) {
    def log = args.logger
    def sutAddr = 'http://www.google.com/'
    def sut = new RESTCli(args, sutAddr, ContentType.HTML)
    sut.get(path: '')
  }
}'''
        db.testCase << [_id: 1L, team: new DBRef(null, 'team', 10L), name: testrunName, owner: new DBRef(null, 'user', user._id), script: testScript, dateCreated: new Date(), lastUpdated: new Date()]
        
        def tc = db.testCase.findOne(name: testrunName)
        db.team << [_id: 10L, name: 'svt', users: [new DBRef(null, 'user', user._id)], testcases: [new DBRef(null, 'testCase', tc._id)]]
    }

    @After
    public void tearDown() throws Exception {
        db.instance.remove([:])
        db.iteration.remove([:])
        db.resultEntry.remove([:])
        db.testRun.remove([:])
        db.category.remove([:])
        db.testCase.remove([:])
        db.user.remove([:])
        db.team.remove([:])
        def dirs = new File(testConfig.test.env).listFiles()
        dirs.each {
            new AntBuilder().delete(dir: it)
        }
    }
    
    @Test
    void repeatTest() { 
        def repetitions = 2
        def users = 2
        
        to LoginPage
        assert at(LoginPage)
        auth.login(testusername, testpw)
        
        // Choose the default test and run it
        to TestRunPage
        assert at(TestRunPage)
        $('#runform').testcase = db.testCase.findOne(name: testrunName)._id
        $('#runform').runtest().jquery.click()
        
        // At the run-test wizard. Enter name, choose to repeat 2 times, then click finish
        $('#runform').trname = testrunName
        $('#wiznext').jquery.click()
        $('#runform').repeatcount = repetitions.toString()
        $('#runform').users = users.toString()
        $('#wizfinish').jquery.click()
        
        assert at(RunningTestsPage)
        assert runningTestsTable.size() == 1
        assert runningTestsTable[0].testname == testrunName
        assert runningTestsTable[0].startdate =~ /^\d\d\/\d\d\/\d{4} \d\d:\d\d:\d\d$/
        
        // Click the "View" button for this completed execution to see the test results
        runningTestsTable[0].view.click(TestResultsPage)
        
        assert at(TestResultsPage)
        stats.contains("Number of iterations: $repetitions")
        stats.contains("Number of users: $users")
        
        //def tr = db.testRun.findOne()
        
        //TODO: Currently not using JavaScript, so we have to keep refreshing the page until the test finishes
        /*def limit = 240000
        def step = 4000
        def elapsedTime = 0
        while (true) {
            if (elapsedTime > limit) {
                fail("test fails to complete after ${limit / 1000} seconds")
            }
            
            // If Duration shows a number, then test has finished
            to TestResultsPage, tr._id
            try {
                waitFor { $('div.section')[repetitions - 1].text() }
            } catch(geb.waiting.WaitTimeoutException e) {}
            
            if ($('div.section')[repetitions - 1].text() =~ /Duration: \d/) {
                break
            }
            
            sleep step
            elapsedTime += step
        }*/
        
        waitFor(60, 2) { $('div.section', repetitions-1).text() =~ /Duration: \d/ }

        // Open all sections
        $('div.section').click()
        repetitions.times { i ->
            waitFor(10, 2) {
                //$('#test' + (i+1)).jquery.click()
                $('pre', i).text().contains('GET http://www.google.com/ content-type:text/html')
            }
            //waitFor(10) { $('pre', i).text().contains('Title: Google') }
        }
        
        details[repetitions - 1].click(TestRunDetailsPage)
        
        assert at(TestRunDetailsPage)
        assert detailsTable.any {
            it.timestamp =~ /^\d\d\/\d\d\/\d{4} \d\d:\d\d:\d\d\.\d{3}$/ \
            && it.type     == 'GET' \
            && it.entry    == 'INFO: http://www.google.com/ content-type:text/html' \
            && it.response =~ /\d+/
        }
    }
}
